home *** CD-ROM | disk | FTP | other *** search
- /*
- * gen.c
- *
- * $Id: gen.c,v 1.15 1994/12/31 21:02:55 parrt Exp parrt $
- * $Revision: 1.15 $
- *
- * Generate C code (ANSI, K&R, C++)
- *
- * SOFTWARE RIGHTS
- *
- * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
- * Set (PCCTS) -- PCCTS is in the public domain. An individual or
- * company may do whatever they wish with source code distributed with
- * PCCTS or the code generated by PCCTS, including the incorporation of
- * PCCTS, or its output, into commerical software.
- *
- * We encourage users to develop software with PCCTS. However, we do ask
- * that credit is given to us for developing PCCTS. By "credit",
- * we mean that if you incorporate our source code into one of your
- * programs (commercial product, research project, or otherwise) that you
- * acknowledge this fact somewhere in the documentation, research report,
- * etc... If you like PCCTS and have developed a nice tool with the
- * output, please mention that you developed it using PCCTS. In
- * addition, we ask that this header remain intact in our source code.
- * As long as these guidelines are kept, we expect to continue enhancing
- * this system and expect to make other tools available as they are
- * completed.
- *
- * ANTLR 1.31
- * Terence Parr
- * Parr Research Corporation
- * with Purdue University and AHPCRC, University of Minnesota
- * 1989-1995
- */
- #include <stdio.h>
- #include <ctype.h>
- #include "set.h"
- #include "syn.h"
- #include "hash.h"
- #include "generic.h"
- #include "dlgdef.h"
-
- #define NumExprPerLine 4
- static int on1line=0;
- static set tokensRefdInBlock;
-
-
- /* T r a n s l a t i o n T
- a b l e s */
-
- /* C_Trans[node type] == pointer to function that knows how to translate that node. */
- #ifdef __cplusplus
- void (*C_Trans[NumNodeTypes+1])(...) = {
- NULL,
- NULL, /* See next table.
- Junctions have many types */
- (void (*)(...)) genRuleRef,
- (void (*)(...)) genToken,
- (void (*)(...)) genAction
- };
- #else
- void (*C_Trans[NumNodeTypes+1])() = {
- NULL,
- NULL, /* See next table.
- Junctions have many types */
- genRuleRef,
- genToken,
- genAction
- };
- #endif
-
- /* C_JTrans[Junction type] == pointer to function that knows how to translate that
- * kind of junction node.
- */
- #ifdef __cplusplus
- void (*C_JTrans[NumJuncTypes+1])(...) = {
- NULL,
- (void (*)(...)) genSubBlk,
- (void (*)(...)) genOptBlk,
- (void (*)(...)) genLoopBlk,
- (void (*)(...)) genEndBlk,
- (void (*)(...)) genRule,
- (void (*)(...)) genJunction,
- (void (*)(...)) genEndRule,
- (void (*)(...)) genPlusBlk,
- (void (*)(...)) genLoopBegin
- };
- #else
- void (*C_JTrans[NumJuncTypes+1])() = {
- NULL,
- genSubBlk,
- genOptBlk,
- genLoopBlk,
- genEndBlk,
- genRule,
- genJunction,
- genEndRule,
- genPlusBlk,
- genLoopBegin
- };
- #endif
-
- #define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t') {s++;}
-
- static int tabs = 0;
- #define TAB { int i; for (i=0; i<tabs; i++) fputc('\t', output); }
- static void
- #ifdef __USE_PROTOS
- tab( void )
- #else
- tab( )
- #endif
- TAB
-
- #ifdef __USE_PROTOS
- static char *tokenFollowSet(TokNode *);
- static ActionNode *findImmedAction( Node * );
- static void dumpRetValAssign(char *, char *);
- static void dumpAfterActions(FILE *output);
- static set ComputeErrorSet(Junction *, int);
- static void makeErrorClause(Junction *, set, int);
- static void DumpFuncHeader( Junction *, RuleEntry * );
- static int has_guess_block_as_first_item(Junction *);
- static int genExprSets(set *, int);
- static void genExprTree( Tree *t, int k );
- #else
- static char *tokenFollowSet();
- static ActionNode *findImmedAction();
- static void dumpRetValAssign();
- static void dumpAfterActions();
- static set ComputeErrorSet();
- static void makeErrorClause();
- static void DumpFuncHeader();
- static int has_guess_block_as_first_item();
- static int genExprSets();
- static void genExprTree();
- #endif
-
- #define gen(s) {tab(); fprintf(output, s);}
- #define gen1(s,a) {tab(); fprintf(output, s,a);}
- #define gen2(s,a,b) {tab(); fprintf(output, s,a,b);}
- #define gen3(s,a,b,c) {tab(); fprintf(output, s,a,b,c);}
- #define gen4(s,a,b,c,d) {tab(); fprintf(output, s,a,b,c,d);}
- #define gen5(s,a,b,c,d,e) {tab(); fprintf(output, s,a,b,c,d,e);}
- #define gen6(s,a,b,c,d,e,f) {tab(); fprintf(output, s,a,b,c,d,e,f);}
- #define gen7(s,a,b,c,d,e,f,g) {tab(); fprintf(output, s,a,b,c,d,e,f,g);}
-
- #define _gen(s) {fprintf(output, s);}
- #define _gen1(s,a) {fprintf(output, s,a);}
- #define _gen2(s,a,b) {fprintf(output, s,a,b);}
- #define _gen3(s,a,b,c) {fprintf(output, s,a,b,c);}
- #define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}
- #define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}
- #define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}
- #define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}
-
- static void
- #ifdef __USE_PROTOS
- warn_about_using_gk_option(void)
- #else
- warn_about_using_gk_option()
- #endif
- {
- static int warned_already=0;
-
- if ( !DemandLookahead || warned_already ) return;
- warned_already = 1;
- warnNoFL("-gk option could cause trouble for <<...>>? predicates");
- }
-
- void
- #ifdef __USE_PROTOS
- freeBlkFsets( Junction *q )
- #else
- freeBlkFsets( q )
- Junction *q;
- #endif
- {
- int i;
- Junction *alt;
- require(q!=NULL, "freeBlkFsets: invalid node");
-
- for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
- {
- for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
- }
- }
-
- /*
- * Generate a local variable allocation for each token references
- * in this block.
- */
- static void
- #ifdef __USE_PROTOS
- genTokenPointers( Junction *q )
- #else
- genTokenPointers( q )
- Junction *q;
- #endif
- {
- /* Rule refs are counted and can be referenced, but their
- * value is not set to anything useful ever.
- *
- * The ptrs are to be named _tij where i is the current level
- * and j is the element number within an alternative.
- */
- int first=1, t;
- set a;
- tokensRefdInBlock = q->tokrefs;
-
- if ( set_deg(q->tokrefs) == 0 ) return;
- a = set_dup(q->tokrefs);
- gen("ANTLRToken ");
- for (; !set_nil(a); set_rm(t, a))
- {
- t = set_int(a);
- if ( first ) first = 0;
- else _gen(",");
- if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);
- _gen2("*_t%d%d", BlkLevel, t);
- if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}
- else _gen("=NULL");
- }
- _gen(";\n");
- set_free(a);
- }
-
- static int
- #ifdef __USE_PROTOS
- hasDefaultException(ExceptionGroup *eg)
- #else
- hasDefaultException(eg)
- ExceptionGroup *eg;
- #endif
- {
- ListNode *q;
-
- for (q = eg->handlers->next; q!=NULL; q=q->next)
- {
- ExceptionHandler *eh = (ExceptionHandler *)q->elem;
- if ( strcmp("default", eh->signalname)==0 ) {
- return 1;
- }
- }
- return 0;
- }
-
- static void
- #ifdef __USE_PROTOS
- dumpException(ExceptionGroup *eg, int no_default_case)
- #else
- dumpException(eg, no_default_case)
- ExceptionGroup *eg;
- int no_default_case;
- #endif
- {
- gen1("switch ( _signal ) {\n", eg->label==NULL?"":eg->label);
- {
- ListNode *q;
- for (q = eg->handlers->next; q!=NULL; q=q->next)
- {
- ExceptionHandler *eh = (ExceptionHandler *)q->elem;
- if ( strcmp("default", eh->signalname)==0 ) {
- gen("default :\n");
- tabs++;
- dumpAction(eh->action, output, tabs, -1, 1, 1);
- gen("_signal = NoSignal;\n");
- tabs--;
- gen("}\n");
- return;
- }
- gen1("case %s :\n", eh->signalname);
- tabs++;
- if ( eh->action != NULL )
- {
- dumpAction(eh->action, output, tabs, -1, 1, 1);
- gen("_signal = NoSignal;\n");
- gen("break;\n");
- }
- tabs--;
- }
- }
- if ( no_default_case ) return;
-
- gen("default :\n");
- tabs++;
- /* gen("*_retsignal = _signal;\n");*/
- gen("goto _handler;\n");
- tabs--;
- gen("}\n");
- }
-
- static void
- #ifdef __USE_PROTOS
- dumpExceptions(ListNode *list)
- #else
- dumpExceptions(list)
- ListNode *list;
- #endif
- {
- ListNode *p;
-
- for (p = list->next; p!=NULL; p=p->next)
- {
- ExceptionGroup *eg = (ExceptionGroup *) p->elem;
- _gen2("%s%s_handler:\n",
- eg->label==NULL?"":eg->label,
- eg->altID==NULL?"":eg->altID);
- if ( eg->altID!=NULL ) dumpException(eg, 0);
- else {
- /* This must be the rule exception handler */
- dumpException(eg, 1);
- if ( !hasDefaultException(eg) )
- {
- gen("default :\n");
- tabs++;
- gen("zzdflthandlers(_signal,_retsignal);\n");
- tabs--;
- gen("}\n");
- }
- }
- }
- }
-
- /* For each element label that is found in a rule, generate a unique
- * Attribute (and AST pointer if GenAST) variable.
- */
- void
- #ifdef __USE_PROTOS
- genElementLabels(ListNode *list)
- #else
- genElementLabels(list)
- ListNode *list;
- #endif
- {
- int first=1;
- ListNode *p;
-
- if ( GenCC ) {gen("ANTLRToken");}
- else {gen("Attrib");}
- for (p = list->next; p!=NULL; p=p->next)
- {
- char *ep = (char *)p->elem;
- if ( first ) first = 0;
- else _gen(",");
- if ( GenCC ) {_gen1(" *%s=NULL",ep);}
- else {_gen1(" %s",ep);}
- }
- _gen(";\n");
-
- if ( !GenAST ) return;
-
- first = 1;
- gen("AST");
- for (p = list->next; p!=NULL; p=p->next)
- {
- char *ep = (char *)p->elem;
- if ( first ) first = 0;
- else _gen(",");
- _gen1(" *%s_ast=NULL",ep);
- }
- _gen(";\n");
- }
-
- /*
- * Generate a local variable allocation for each token or rule reference
- * in this block.
- */
- static void
- #ifdef __USE_PROTOS
- genASTPointers( Junction *q )
- #else
- genASTPointers( q )
- Junction *q;
- #endif
- {
- int first=1, t;
- set a;
-
- a = set_or(q->tokrefs, q->rulerefs);
- if ( set_deg(a) > 0 )
- {
- gen("AST ");
- for (; !set_nil(a); set_rm(t, a))
- {
- t = set_int(a);
- if ( first ) first = 0;
- else _gen(",");
- _gen2("*_ast%d%d=NULL", BlkLevel, t);
- }
- set_free(a);
- }
- _gen(";\n");
- }
-
- static void
- #ifdef __USE_PROTOS
- BLOCK_Head( void )
- #else
- BLOCK_Head( )
- #endif
- {
- gen("{\n");
- tabs++;
- if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
- }
-
- static void
- #ifdef __USE_PROTOS
- BLOCK_Tail( void )
- #else
- BLOCK_Tail( )
- #endif
- {
- if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
- if ( !GenCC ) gen("}\n");
- tabs--;
- gen("}\n");
- }
-
- static void
- #ifdef __USE_PROTOS
- BLOCK_Preamble( Junction *q )
- #else
- BLOCK_Preamble( q )
- Junction *q;
- #endif
- {
- ActionNode *a;
- Junction *begin;
-
- BLOCK_Head();
- if ( GenCC ) genTokenPointers(q);
- if ( GenCC&&GenAST ) genASTPointers(q);
- if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");
- if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)
- else if ( !GenCC ) gen("zzMake0;\n");
- if ( !GenCC ) gen("{\n");
- if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);
- else begin = q;
- if ( has_guess_block_as_first_item(begin) )
- {
- gen("zzGUESS_BLOCK\n");
- }
- if ( q->jtype == aLoopBegin )
- a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */
- else
- a = findImmedAction( q->p1 );
- if ( a!=NULL && !a->is_predicate ) {
- dumpAction(a->action, output, tabs, a->file, a->line, 1);
- a->done = 1; /* remove action. We have already handled it */
- }
- }
-
- /* If predicates are allowed in parsing expressions:
- *
- * ( production 1
- * | production 2
- * ...
- * | production n
- * )
- *
- * where production 1 yields visible predicates: <<pred>>? <<pred2>>?
- *
- * generates (if -prc on):
- *
- * if ( (production 1 prediction) &&
- * (context_of_pred && pred) &&
- * (context_of_pred2 && pred2) ) {
- * ...
- * }
- * else if ( production 2 prediction ) {
- * ...
- * }
- * ...
- *
- * p1
- * |
- * p2--p3
- *
- * results in
- *
- * if ( (production 1 prediction) &&
- * (context_of_p1 && p1) &&
- * ((context_of_p2 && p2)||
- * (context_of_p3 && p3)) &&
- * ) {
- * ...
- * }
- *
- * If no context, then just test expression.
- */
- void
- #ifdef __USE_PROTOS
- genPredTree( Predicate *p, Junction *j )
- #else
- genPredTree( p, j )
- Predicate *p;
- Junction *j;
- #endif
- {
- int context_was_present = 0;
-
- _gen("(");
- for (; p!=NULL; p=p->right)
- {
- if ( HoistPredicateContext )
- {
- context_was_present = 0;
- if ( LL_k>1 && p->tcontext!=NULL )
- {
- context_was_present = 1;
- _gen("((");
- genExprTree(p->tcontext, 1);
- _gen(") ? ");
- }
- else if ( LL_k==1 && set_deg(p->scontext[1])>0 )
- {
- context_was_present = 1;
- _gen("((");
- genExprSets(&(p->scontext[0]), CLL_k);
- _gen(") ? ");
- }
- }
-
- if ( FoundException ) {_gen("(_sva=(");}
- else {_gen("(");}
- dumpAction(p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);
- if ( FoundException ) {_gen("))");}
- else {_gen(")");}
-
- if ( HoistPredicateContext && context_was_present ) _gen(" : 1)");
-
- if ( p->down!=NULL )
- {
- _gen("&&");
- genPredTree(p->down, j);
- }
-
- if ( p->right!=NULL ) _gen("||");
- }
- _gen(")");
- }
-
- static void
- #ifdef __USE_PROTOS
- genExprTree( Tree *t, int k )
- #else
- genExprTree( t, k )
- Tree *t;
- int k;
- #endif
- {
- require(t!=NULL, "genExprTree: NULL tree");
-
- if ( t->token == ALT )
- {
- _gen("("); genExprTree(t->down, k); _gen(")");
- if ( t->right!=NULL )
- {
- _gen("||");
- on1line++;
- if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
- _gen("("); genExprTree(t->right, k); _gen(")");
- }
- return;
- }
- if ( t->down!=NULL ) _gen("(");
- _gen1("LA(%d)==",k);
- if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
- else _gen1("%s", TokenString(t->token));
- if ( t->down!=NULL )
- {
- _gen("&&");
- on1line++;
- if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
- _gen("("); genExprTree(t->down, k+1); _gen(")");
- }
- if ( t->down!=NULL ) _gen(")");
- if ( t->right!=NULL )
- {
- _gen("||");
- on1line++;
- if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
- _gen("("); genExprTree(t->right, k); _gen(")");
- }
- }
-
- /*
- * Generate LL(k) type expressions of the form:
- *
- * (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
- * (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
- * .....
- * (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
- *
- * If GenExprSets generate:
- *
- * (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
- *
- * where n is set_deg(expr) and Ti is some random token and k is the last nonempty
- * set in fset <=CLL_k.
- * k=1..CLL_k where CLL_k >= 1.
- *
- * This routine is visible only to this file and cannot answer a TRANS message.
- *
- */
- static int
- #ifdef __USE_PROTOS
- genExpr( Junction *j )
- #else
- genExpr( j )
- Junction *j;
- #endif
- {
- int max_k;
-
- /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
- * from CLL_k..LL_k
- */
- {
- int limit;
- if ( j->ftree!=NULL ) limit = LL_k;
- else limit = CLL_k;
- max_k = genExprSets(j->fset, limit);
- }
-
- /* Do tests for real tuples from other productions that conflict with
- * artificial tuples generated by compression (using sets of tokens
- * rather than k-trees).
- */
- if ( j->ftree != NULL )
- {
- _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
- }
-
- if ( ParseWithPredicates && j->predicate!=NULL )
- {
- Predicate *p = j->predicate;
- warn_about_using_gk_option();
- _gen("&&");
- genPredTree(p, j);
- }
-
- return max_k;
- }
-
- static int
- #ifdef __USE_PROTOS
- genExprSets( set *fset, int limit )
- #else
- genExprSets( fset, limit )
- set *fset;
- int limit;
- #endif
- {
- int k = 1;
- int max_k = 0;
- unsigned *e, *g, firstTime=1;
-
- if ( GenExprSets )
- {
- while ( !set_nil(fset[k]) && k<=limit )
- {
- if ( set_deg(fset[k])==1 ) /* too simple for a set? */
- {
- int e;
- _gen1("(LA(%d)==",k);
- e = set_int(fset[k]);
- if ( TokenString(e) == NULL ) _gen1("%d)", e)
- else _gen1("%s)", TokenString(e));
- }
- else
- {
- NewSet();
- FillSet( fset[k] );
- _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
- }
- if ( k>max_k ) max_k = k;
- if ( k == CLL_k ) break;
- k++;
- if ( !set_nil(fset[k]) && k<=limit ) _gen(" && ");
- on1line++;
- if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
- }
- return max_k;
- }
-
- while ( !set_nil(fset[k]) && k<=limit )
- {
- if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");
- for (; *e!=nil; e++)
- {
- if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
- on1line++;
- if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
- _gen1("LA(%d)==",k);
- if ( TokenString(*e) == NULL ) _gen1("%d", *e)
- else _gen1("%s", TokenString(*e));
- }
- free( (char *)g );
- _gen(")");
- if ( k>max_k ) max_k = k;
- if ( k == CLL_k ) break;
- k++;
- if ( !set_nil(fset[k]) && k<=limit ) { firstTime=1; _gen(" && "); }
- on1line++;
- if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
- }
- return max_k;
- }
-
- /*
- * Generate code for any type of block. If the last alternative in the block is
- * empty (not even an action) don't bother doing it. This permits us to handle
- * optional and loop blocks as well.
- *
- * Only do this block, return after completing the block.
- * This routine is visible only to this file and cannot answer a TRANS message.
- */
- static set
- #ifdef __USE_PROTOS
- genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly )
- #else
- genBlk( q, jtype, max_k, need_right_curly )
- Junction *q;
- int jtype;
- int *max_k;
- int *need_right_curly;
- #endif
- {
- set f;
- Junction *alt;
- int a_guess_in_block = 0;
- require(q!=NULL, "genBlk: invalid node");
- require(q->ntype == nJunction, "genBlk: not junction");
-
- *need_right_curly=0;
- if ( q->p2 == NULL ) /* only one alternative? Then don't need if */
- {
- if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
- {
- warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);
- gen("zzGUESS\n"); /* guess anyway to make output code consistent */
- gen("if ( !zzrv )\n");
- }
- TRANS(q->p1);
- return empty; /* no decision to be made-->no error set */
- }
-
- f = First(q, 1, jtype, max_k);
- for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
- {
- if ( alt->p2 == NULL ) /* chk for empty alt */
- {
- Node *p = alt->p1;
- if ( p->ntype == nJunction )
- {
- /* we have empty alt */
- if ( ((Junction *)p)->p1 == (Node *)q->end )
- {
- break; /* don't do this one, quit */
- }
- }
- }
- if ( alt != q ) gen("else ")
- else
- {
- if ( DemandLookahead )
- if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
- else gen1("look(%d);\n", *max_k);
- }
- if ( alt!=q )
- {
- _gen("{\n");
- tabs++;
- (*need_right_curly)++;
- /* code to restore state if a prev alt didn't follow guess */
- if ( a_guess_in_block )
- if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_DONE;\n");}
- else gen("if ( guessing ) zzGUESS_DONE;\n");
- }
- if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
- {
- a_guess_in_block = 1;
- gen("zzGUESS\n");
- }
- gen("if ( ");
- if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
- genExpr(alt);
- _gen(" ) ");
- _gen("{\n");
- tabs++;
- TRANS(alt->p1);
- --tabs;
- gen("}\n");
- }
- return f;
- }
-
- static int
- #ifdef __USE_PROTOS
- has_guess_block_as_first_item( Junction *q )
- #else
- has_guess_block_as_first_item( q )
- Junction *q;
- #endif
- {
- Junction *alt;
-
- for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
- {
- if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
- }
- return 0;
- }
-
- /* return NULL if 1st item of alt is (...)? block; else return ptr
- to aSubBlk node
- * of (...)?; This function ignores actions and predicates.
- */
- Junction *
- #ifdef __USE_PROTOS
- first_item_is_guess_block( Junction *q )
- #else
- first_item_is_guess_block( q )
- Junction *q;
- #endif
- {
- while ( q!=NULL && ((q->ntype==nJunction && q->jtype==Generic) || q->ntype==nAction) )
- {
- if ( q->ntype==nJunction ) q = (Junction *)q->p1;
- else q = (Junction *) ((ActionNode *)q)->next;
- }
-
- if ( q==NULL ) return NULL;
- if ( q->ntype!=nJunction ) return NULL;
- if ( q->jtype!=aSubBlk ) return NULL;
- if ( !q->guess ) return NULL;
- return q;
- }
-
- /* Generate an action. Don't if action is NULL which means that it was already
- * handled as an init action.
- */
- void
- #ifdef __USE_PROTOS
- genAction( ActionNode *p )
- #else
- genAction( p )
- ActionNode *p;
- #endif
- {
- require(p!=NULL, "genAction: invalid node and/or rule");
- require(p->ntype==nAction, "genAction: not action");
-
- if ( !p->done )
- {
- if ( p->is_predicate )
- {
- gen("if (!(");
- /* make sure that '#line n' is on front of line */
- if ( GenLineInfo && p->file != -1 ) _gen("\n");
- dumpAction(p->action, output, 0, p->file, p->line, 0);
- if ( p->pred_fail != NULL )
- {
- _gen("))\n");
- /* if ( FoundGuessBlk ) gen("zzNON_GUESS_MODE {\n");*/
- tabs++;
- gen1("%s;\n", p->pred_fail);
- tabs--;
- /* if ( FoundGuessBlk ) gen("}\n");*/
- }
- else _gen1(")) {zzfailed_pred((ANTLRChar *)\"%s\");}\n",p->action);
- }
- else
- {
- if ( FoundGuessBlk )
- if ( GenCC ) {gen("if ( !guessing ) {\n");}
- else gen("zzNON_GUESS_MODE {\n");
- dumpAction(p->action, output, tabs, p->file, p->line, 1);
- if ( FoundGuessBlk ) gen("}\n");
- }
- }
- TRANS(p->next)
- }
-
- /*
- * if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in
- * else pass addr of temp root ptr (&_ast) (don't zzlink it in).
- *
- * if ! modifies rule-ref, then never link it in and never pass zzSTR.
- * Always pass address of temp root ptr.
- */
- void
- #ifdef __USE_PROTOS
- genRuleRef( RuleRefNode *p )
- #else
- genRuleRef( p )
- RuleRefNode *p;
- #endif
- {
- Junction *q;
- char *handler_id = "";
- RuleEntry *r, *r2;
- char *parm = "", *exsig = "";
- require(p!=NULL, "genRuleRef: invalid node and/or rule");
- require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
-
- if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
- handler_id = p->altstart->exception_label;
-
- r = (RuleEntry *) hash_get(Rname, p->text);
- if ( r == NULL )
- {
- warnFL( eMsg1("rule %s not defined",
- p->text), FileStr[p->file], p->line );
- return;
- }
- r2 = (RuleEntry *) hash_get(Rname, p->rname);
- if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
-
- if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
-
- if ( GenCC && GenAST ) {
- gen("_ast = NULL;\n");
- }
-
- if ( FoundGuessBlk && p->assign!=NULL )
- if ( GenCC ) {gen("if ( !guessing ) {\n");}
- else gen("zzNON_GUESS_MODE {\n");
-
- if ( FoundException ) exsig = "&_signal";
-
- tab();
- if ( GenAST )
- {
- if ( GenCC ) {
- /* if ( r2->noAST || p->astnode==ASTexclude )
- */
- {
- /* _gen("_ast = NULL;\n");*/
- parm = "&_ast";
- }
- /* we always want to set just a pointer now, then set correct
- pointer after
-
- else {
- _gen("_astp =
- (_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
- parm = "_astp";
- }
- */
- }
- else {
- if ( r2->noAST || p->astnode==ASTexclude )
- {
- _gen("_ast = NULL; ");
- parm = "&_ast";
- }
- else parm = "zzSTR";
- }
- if ( p->assign!=NULL )
- {
- if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
- else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
- }
- if ( FoundException ) {
- _gen5("%s%s(%s,&_signal%s%s); ",
- RulePrefix,
- p->text,
- parm,
- (p->parms!=NULL)?",":"",
- (p->parms!=NULL)?p->parms:"");
- if ( p->ex_group!=NULL ) {
- _gen("\n");
- gen("if (_signal) {\n");
- tabs++;
- dumpException(p->ex_group, 0);
- tabs--;
- gen("}");
- }
- else {
- _gen1("if (_signal) goto %s_handler;", handler_id);
- }
- }
- else {
- _gen5("%s%s(%s%s%s);",
- RulePrefix,
- p->text,
- parm,
- (p->parms!=NULL)?",":"",
- (p->parms!=NULL)?p->parms:"");
- }
- if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )
- {
- /* rule has a ! or element does */
- /* still need to assign to #i so we can play with it */
- _gen("\n");
- gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);
- }
- else if ( !r2->noAST && p->astnode == ASTinclude )
- {
- /* rule doesn't have a ! and neither does element */
- if ( GenCC ) {
- _gen("\n");
- gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");
- gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);
- tab();
- }
- else _gen(" ");
- if ( GenCC ) {_gen("ASTBase::");} else _gen("zz");
- _gen("link(_root, &_sibling, &_tail);");
- }
- }
- else
- {
- if ( p->assign!=NULL )
- {
- if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
- else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
- }
- if ( FoundException ) {
- _gen4("%s%s(&_signal%s%s); ",
- RulePrefix,
- p->text,
- (p->parms!=NULL)?",":"",
- (p->parms!=NULL)?p->parms:"");
- if ( p->ex_group!=NULL ) {
- _gen("\n");
- gen("if (_signal) {\n");
- tabs++;
- dumpException(p->ex_group, 0);
- tabs--;
- gen("}");
- }
- else {
- _gen1("if (_signal) goto %s_handler;", handler_id);
- }
- }
- else {
- _gen3("%s%s(%s);",
- RulePrefix,
- p->text,
- (p->parms!=NULL)?p->parms:"");
- }
- if ( p->assign!=NULL ) _gen("\n");
- }
- q = RulePtr[r->rulenum]; /* find definition of ref'd rule */
- if ( p->assign!=NULL ) {
- if ( HasComma(p->assign) )
- {
- _gen("\n");
- dumpRetValAssign(p->assign, q->ret);
- _gen("}");
- }
- }
- _gen("\n");
-
- /* Handle element labels now */
- if ( p->el_label!=NULL )
- {
- if ( GenAST )
- {
- if ( GenCC ) {
- gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
- }
- else {gen1("%s_ast = zzastCur;\n", p->el_label);}
- }
- }
-
- if ( FoundGuessBlk && p->assign!=NULL ) {
- /* in guessing mode, don't branch to handler upon error */
- gen("} else {\n");
- if ( FoundException ) {
- gen6("%s%s(%s%s&_signal%s%s);\n",
- RulePrefix,
- p->text,
- parm,
- (*parm!='\0')?",":"",
- (p->parms!=NULL)?",":"",
- (p->parms!=NULL)?p->parms:"");
- }
- else {
- gen5("%s%s(%s%s%s);\n",
- RulePrefix,
- p->text,
- parm,
- (p->parms!=NULL && *parm!='\0')?",":"",
- (p->parms!=NULL)?p->parms:"");
- }
- gen("}\n");
- }
- TRANS(p->next)
- }
-
- /*
- * Generate code to match a token.
- *
- * Getting the next token is tricky. We want to ensure that any action
- * following a token is executed before the next GetToken();
- */
- void
- #ifdef __USE_PROTOS
- genToken( TokNode *p )
- #else
- genToken( p )
- TokNode *p;
- #endif
- {
- TermEntry *tcsym;
- RuleEntry *r;
- char *handler_id = "";
- ActionNode *a;
- require(p!=NULL, "genToken: invalid node and/or rule");
- require(p->ntype==nToken, "genToken: not token");
-
- if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
- handler_id = p->altstart->exception_label;
-
- r = (RuleEntry *) hash_get(Rname, p->rname);
- if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
-
- if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
-
- if ( !set_nil(p->tset) )
- {
- unsigned e;
- set b;
- b = set_dup(p->tset);
- #ifdef DUM
- tcsym = (TermEntry *)hash_get(Tname, TokenString(p->token));
- require(tcsym!=NULL, "cannot find tokclass in sym tab");
- if ( tcsym->tclass->dumped ) e = tcsym->tclass->setnum;
- #else
- if ( p->tclass->dumped ) e = p->tclass->setnum;
- #endif
- else {
- e = DefErrSet(&b, 0, TokenString(p->token));
- p->tclass->dumped = 1; /* indicate that a set has been created */
- #ifdef DUM
- tcsym->tclass->setnum = e;
- #else
- p->tclass->setnum = e;
- #endif
- }
- if ( !FoundException )
- {gen1("zzsetmatch(%s_set);", TokenString(p->token));}
- else {
- if ( p->use_def_MT_handler )
- gen3("zzsetmatch_wdfltsig(%s_set,(TokenType)%d,%s);",
- TokenString(p->token),
- p->token,
- tokenFollowSet(p))
- else
- gen2("zzsetmatch_wsig(%s_set, %s_handler);",
- TokenString(p->token),
- handler_id);
- }
- set_free(b);
- }
- else if ( TokenString(p->token)!=NULL )
- {
- if ( FoundException ) {
- if ( p->use_def_MT_handler )
- gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p))
- else
- gen2("zzmatch_wsig(%s, %s_handler);",
- TokenString(p->token),
- handler_id);
- }
- else gen1("zzmatch(%s);", TokenString(p->token));
- }
- else {
- if ( FoundException ) {
- if ( p->use_def_MT_handler )
- gen2("zzmatch_wdfltsig((TokenType)%d,%s);",
- p->token,tokenFollowSet(p))
- else
- gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);
- }
- else {gen1("zzmatch(%d);", p->token);}
- }
-
- a = findImmedAction( p->next );
- /* generate the token copies */
- if ( GenCC && p->elnum>0 )
- {
- /* If building trees in C++, always gen the LT() assigns */
- if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {
- if ( !DontCopyTokens )
- {_gen2(" *_t%d%d = *((ANTLRToken *)LT(1));", BlkLevel-1, p->elnum);}
- else
- _gen2(" _t%d%d = (ANTLRToken *)LT(1);", BlkLevel-1, p->elnum);
- }
- if ( LL_k>1 )
- if ( !DemandLookahead ) _gen(" labase++;");
- _gen("\n");
- tab();
- }
- if ( GenAST )
- {
- if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
- {
- if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
- else {_gen("zzNON_GUESS_MODE {\n"); tab();}
- }
- if ( !r->noAST )
- {
- if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
- _gen("\n");
- gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
- tab();
- }
- if ( GenCC && !(p->astnode == ASTexclude || r->noAST) )
- {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
- else _gen(" ");
- if ( p->astnode==ASTchild ) {
- if ( !GenCC ) _gen("zz");
- _gen("subchild(_root, &_sibling, &_tail);");
- }
- else if ( p->astnode==ASTroot ) {
- if ( !GenCC ) _gen("zz");
- _gen("subroot(_root, &_sibling, &_tail);");
- }
- if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
- _gen("\n");
- tab();
- }
- }
- else if ( !GenCC ) _gen(" zzastDPush;");
- if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
- {_gen("}\n"); tab();}
- }
-
- /* Handle element labels now */
- if ( p->el_label!=NULL )
- {
- _gen("\n");
- if ( FoundGuessBlk )
- {
- if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
- else {gen("zzNON_GUESS_MODE {\n"); tab();}
- }
- /* Do Attrib / Token ptr */
- if ( GenCC ) {
- if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
- {gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);}
- else
- {gen1("%s = (ANTLRToken *)LT(1);\n", p->el_label);}
- }
- else {gen1("%s = zzaCur;\n", p->el_label);}
- /* Do AST ptr */
- if ( GenAST && !(p->astnode == ASTexclude || r->noAST) )
- {
- if ( GenCC ) {
- gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
- }
- else {gen1("%s_ast = zzastCur;\n", p->el_label);}
- }
-
- if ( FoundGuessBlk ) {_gen("}\n"); tab();}
- }
-
- /* Handle any actions immediately following action */
- if ( a != NULL )
- {
- /* delay next token fetch until after action */
- _gen("\n");
- if ( a->is_predicate )
- {
- gen("if (!(");
- dumpAction(a->action, output, 0, a->file, a->line, 0);
- if ( a->pred_fail != NULL )
- {
- _gen("))\n");
- /* if ( FoundGuessBlk )
- gen("zzNON_GUESS_MODE {\n");*/
- tabs++;
- gen1("%s;\n", a->pred_fail);
- tabs--;
- /* if ( FoundGuessBlk ) gen("}\n");*/
- }
- else _gen1(")) {zzfailed_pred((ANTLRChar *)\"%s\");}\n",a->action);
- }
- else
- {
- if ( FoundGuessBlk )
- if ( GenCC ) {gen("if ( !guessing ) {\n");}
- else gen("zzNON_GUESS_MODE {\n");
- dumpAction(a->action, output, tabs, a->file, a->line, 1);
- if ( FoundGuessBlk ) gen("}\n");
- }
- a->done = 1;
- if ( !DemandLookahead ) {
- if ( GenCC ) {
- if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");
- _gen(" consume();")
- if ( FoundException && p->use_def_MT_handler )
- _gen(" _signal=NoSignal;");
- _gen("\n");
- }
- else {
- if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)");
- _gen(" zzCONSUME;\n");
- if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
- _gen("\n");
- }
- }
- else gen("\n");
- TRANS( a->next );
- }
- else
- {
- if ( !DemandLookahead ) {
- if ( GenCC ) {
- if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
- _gen(" consume();")
- if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");
- _gen("\n");
- }
- else {
- if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
- _gen(" zzCONSUME;");
- if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
- _gen("\n");
- }
- }
- else _gen("\n");
- TRANS(p->next);
- }
- }
-
- void
- #ifdef __USE_PROTOS
- genOptBlk( Junction *q )
- #else
- genOptBlk( q )
- Junction *q;
- #endif
- {
- int max_k;
- set f;
- int need_right_curly;
- require(q!=NULL, "genOptBlk: invalid node and/or rule");
- require(q->ntype == nJunction, "genOptBlk: not junction");
- require(q->jtype == aOptBlk, "genOptBlk: not optional block");
-
- if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
- BLOCK_Preamble(q);
- BlkLevel++;
- f = genBlk(q, aOptBlk, &max_k, &need_right_curly);
- set_free(f);
- freeBlkFsets(q);
- BlkLevel--;
- if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
- {
- if ( !GenCC ) {gen("else if ( zzguessing ) zzGUESS_DONE;\n");}
- else gen("else if ( guessing ) zzGUESS_DONE;\n");
- }
- { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
- BLOCK_Tail();
- if (q->end->p1 != NULL) TRANS(q->end->p1);
- }
-
- /*
- * Generate code for a loop blk of form:
- *
- * |---|
- * v |
- * --o-G-o-->o--
- */
- void
- #ifdef __USE_PROTOS
- genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
- #else
- genLoopBlk( begin, q, start, max_k )
- Junction *begin;
- Junction *q;
- Junction *start; /* where to start generating code from */
- int max_k;
- #endif
- {
- set f;
- int need_right_curly;
- set savetkref;
- savetkref = tokensRefdInBlock;
- require(q->ntype == nJunction, "genLoopBlk: not junction");
- require(q->jtype == aLoopBlk, "genLoopBlk: not loop block");
-
- if ( q->visited ) return;
- q->visited = TRUE;
- if ( q->p2 == NULL ) /* only one alternative? */
- {
- if ( DemandLookahead )
- if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
- else gen1("look(%d);\n", max_k);
- gen("while ( ");
- if ( begin!=NULL ) genExpr(begin);
- else genExpr(q);
- /* if no predicates have been hoisted for this single alt (..)*
- * do so now
- */
- if ( ParseWithPredicates && begin->predicate==NULL )
- {
- Predicate *a = find_predicates((Node *)q->p1);
- if ( a!=NULL )
- {
- _gen("&&");
- genPredTree(a, q);
- }
- }
- _gen(" ) {\n");
- tabs++;
- TRANS(q->p1);
- if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
- if ( DemandLookahead )
- if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
- else gen1("look(%d);\n", max_k);
- --tabs;
- gen("}\n");
- freeBlkFsets(q);
- q->visited = FALSE;
- tokensRefdInBlock = savetkref;
- return;
- }
- gen("while ( 1 ) {\n");
- tabs++;
- if ( begin!=NULL )
- {
- if ( DemandLookahead )
- {
- if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
- else gen1("look(%d);\n", max_k);
- }
- /* The bypass arc of the (...)* predicts what to do when you fail, but
- * ONLY after having tested the loop start expression. To avoid this,
- * we simply break out of the (...)* loop when we find something that
- * is not in the prediction of the loop (all alts thereof).
- */
- gen("if ( !(");
-
- /* TJP says: It used to use the prediction expression for the bypass arc
- of the (...)*. HOWEVER, if a non LL^1(k) decision was found, this
- thing would miss the ftree stored in the aLoopBegin node and generate
- an LL^1(k) decision anyway.
-
- genExpr((Junction *)begin->p2);
- */
-
- genExpr((Junction *)begin);
- _gen(")) break;\n");
- }
- f = genBlk(q, aLoopBlk, &max_k, &need_right_curly);
- set_free(f);
- freeBlkFsets(q);
-
- /* generate code for terminating loop (this is optional branch) */
- if ( begin==NULL ) gen("else break;\n"); /* code for exiting loop "for sure" */
-
- { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
- if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
- --tabs;
- gen("}\n");
- q->visited = FALSE;
- tokensRefdInBlock = savetkref;
- }
-
- /*
- * Generate code for a loop blk of form:
- *
- * |---|
- * v |
- * --o-->o-->o-G-o-->o--
- * | ^
- * v |
- * o-----------o
- *
- * q->end points to the last node (far right) in the blk. Note
- that q->end->jtype
- * must be 'EndBlk'.
- *
- * Generate code roughly of the following form:
- *
- * do {
- * ... code for alternatives ...
- * } while ( First Set of aLoopBlk );
- *
- * OR if > 1 alternative
- *
- * do {
- * ... code for alternatives ...
- * else break;
- * } while ( 1 );
- */
- void
- #ifdef __USE_PROTOS
- genLoopBegin( Junction *q )
- #else
- genLoopBegin( q )
- Junction *q;
- #endif
- {
- set f;
- int i;
- int max_k;
- set savetkref;
- savetkref = tokensRefdInBlock;
- require(q!=NULL, "genLoopBegin: invalid node and/or rule");
- require(q->ntype == nJunction, "genLoopBegin: not junction");
- require(q->jtype == aLoopBegin, "genLoopBegin: not loop block");
- require(q->p2!=NULL, "genLoopBegin: invalid Loop Graph");
-
- if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
-
- BLOCK_Preamble(q);
- BlkLevel++;
- f = First(q, 1, aLoopBegin, &max_k);
- /* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */
- if ( LL_k>1 && !set_nil(q->fset[2]) )
- genLoopBlk( q, (Junction *)q->p1, q, max_k );
- else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );
-
- for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);
- for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);
- --BlkLevel;
- BLOCK_Tail();
- set_free(f);
- if (q->end->p1 != NULL) TRANS(q->end->p1);
- tokensRefdInBlock = savetkref;
- }
-
- /*
- * Generate code for a loop blk of form:
- *
- * |---|
- * v |
- * --o-G-o-->o--
- *
- * q->end points to the last node (far right) in the blk.
- * Note that q->end->jtype must be 'EndBlk'.
- *
- * Generate code roughly of the following form:
- *
- * do {
- * ... code for alternatives ...
- * } while ( First Set of aPlusBlk );
- *
- * OR if > 1 alternative
- *
- * do {
- * ... code for alternatives ...
- * else if not 1st time through, break;
- * } while ( 1 );
- */
- void
- #ifdef __USE_PROTOS
- genPlusBlk( Junction *q )
- #else
- genPlusBlk( q )
- Junction *q;
- #endif
- {
- int max_k;
- set f;
- int need_right_curly;
- set savetkref;
- savetkref = tokensRefdInBlock;
- require(q!=NULL, "genPlusBlk: invalid node and/or rule");
- require(q->ntype == nJunction, "genPlusBlk: not junction");
- require(q->jtype == aPlusBlk, "genPlusBlk: not Plus block");
- require(q->p2 != NULL, "genPlusBlk: not a valid Plus block");
-
- if ( q->visited ) return;
- q->visited = TRUE;
- if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
- BLOCK_Preamble(q);
- BlkLevel++;
- /* if the ignore flag is set on the 2nd alt and that alt is empty,
- * then it is the implied optional alternative that we added for (...)+
- * and, hence, only 1 alt.
- */
- if ( ((Junction *)q->p2)->p2 == NULL &&
- ((Junction *)q->p2)->ignore ) /* only one alternative? */
- {
- Predicate *a=NULL;
- /* if the only alt has a semantic predicate, hoist it; must test before
- * entering loop.
- */
- if ( ParseWithPredicates )
- {
- a = find_predicates((Node *)q);
- if ( a!=NULL ) {
- gen("if (");
- genPredTree(a, q);
- _gen(") {\n");
- }
- }
- gen("do {\n");
- tabs++;
- TRANS(q->p1);
- if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
- f = First(q, 1, aPlusBlk, &max_k);
- if ( DemandLookahead )
- if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
- else gen1("look(%d);\n", max_k);
- --tabs;
- gen("} while ( ");
- if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
- genExpr(q);
- if ( ParseWithPredicates && a!=NULL )
- {
- _gen("&&");
- genPredTree(a, q);
- }
- _gen(" );\n");
- if ( ParseWithPredicates && a!=NULL ) gen("}\n");
- --BlkLevel;
- BLOCK_Tail();
- q->visited = FALSE;
- freeBlkFsets(q);
- set_free(f);
- if (q->end->p1 != NULL) TRANS(q->end->p1);
- tokensRefdInBlock = savetkref;
- return;
- }
- gen("do {\n");
- tabs++;
- f = genBlk(q, aPlusBlk, &max_k, &need_right_curly);
- gen("else if ( zzcnt>1 ) break; /* implied exit branch */\n");/* code for exiting loop */
- tab();
- makeErrorClause(q,f,max_k);
- { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
- freeBlkFsets(q);
- gen("zzcnt++;");
- if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
- _gen("\n");
- if ( DemandLookahead )
- if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
- else gen1("look(%d);\n", max_k);
- --tabs;
- if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
- else gen("} while ( 1 );\n");
- --BlkLevel;
- BLOCK_Tail();
- q->visited = FALSE;
- if (q->end->p1 != NULL) TRANS(q->end->p1);
- tokensRefdInBlock = savetkref;
- }
-
- /*
- * Generate code for a sub blk of alternatives of form:
- *
- * --o-G1--o--
- * | ^
- * v /|
- * o-G2-o|
- * | ^
- * v |
- * ..........
- * | ^
- * v /
- * o-Gn-o
- *
- * q points to the 1st junction of blk (upper-left).
- * q->end points to the last node (far right) in the blk.
- * Note that q->end->jtype must be 'EndBlk'.
- * The last node in every alt points to q->end.
- *
- * Generate code of the following form:
- * if ( First(G1) ) {
- * ...code for G1...
- * }
- * else if ( First(G2) ) {
- * ...code for G2...
- * }
- * ...
- * else {
- * ...code for Gn...
- * }
- */
- void
- #ifdef __USE_PROTOS
- genSubBlk( Junction *q )
- #else
- genSubBlk( q )
- Junction *q;
- #endif
- {
- int max_k;
- set f;
- int need_right_curly;
- set savetkref;
- savetkref = tokensRefdInBlock;
- require(q->ntype == nJunction, "genSubBlk: not junction");
- require(q->jtype == aSubBlk, "genSubBlk: not subblock");
-
- if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
- BLOCK_Preamble(q);
- BlkLevel++;
- f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
- if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
- { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
- freeBlkFsets(q);
- --BlkLevel;
- BLOCK_Tail();
-
- if ( q->guess )
- {
- gen("zzGUESS_DONE\n");
- }
-
- /* must duplicate if (alpha)?; one guesses (validates), the
- * second pass matches */
- if ( q->guess && analysis_point(q)==q )
- {
- if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
- BLOCK_Preamble(q);
- BlkLevel++;
- f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
- if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
- { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
- freeBlkFsets(q);
- --BlkLevel;
- BLOCK_Tail();
- }
-
- if (q->end->p1 != NULL) TRANS(q->end->p1);
- tokensRefdInBlock = savetkref;
- }
-
- /*
- * Generate code for a rule.
- *
- * rule--> o-->o-Alternatives-o-->o
- * Or,
- * rule--> o-->o-Alternative-o-->o
- *
- * The 1st junction is a RuleBlk. The second can be a SubBlk or just a junction
- * (one alternative--no block), the last is EndRule.
- * The second to last is EndBlk if more than one alternative exists in the rule.
- *
- * To get to the init-action for a rule, we must bypass the RuleBlk,
- * and possible SubBlk.
- * Mark any init-action as generated so genBlk() does not regenerate it.
- */
- void
- #ifdef __USE_PROTOS
- genRule( Junction *q )
- #else
- genRule( q )
- Junction *q;
- #endif
- {
- int max_k;
- set follow, rk, f;
- ActionNode *a;
- RuleEntry *r;
- static int file = -1;
- int need_right_curly;
- require(q->ntype == nJunction, "genRule: not junction");
- require(q->jtype == RuleBlk, "genRule: not rule");
-
- r = (RuleEntry *) hash_get(Rname, q->rname);
- if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");
- if ( q->file != file ) /* open new output file if need to */
- {
- if ( output != NULL ) fclose( output );
- output = fopen(OutMetaName(outname(FileStr[q->file])), "w");
- require(output != NULL, "genRule: can't open output file");
-
- special_fopen_actions(OutMetaName(outname(FileStr[q->file])));
-
- if ( file == -1 ) genHdr1(q->file);
- else genHdr(q->file);
- file = q->file;
- }
- DumpFuncHeader(q,r);
- tabs++;
- if ( q->ret!=NULL )
- {
- if ( HasComma(q->ret) ) {gen1("struct _rv%d _retv;\n",r->rulenum);}
- else
- {
- tab();
- DumpType(q->ret, output);
- gen(" _retv;\n");
- }
- }
-
- if ( GenLineInfo )
- {
- fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
- }
-
- gen("zzRULE;\n");
- if ( FoundException )
- {
- gen("int _sva=1;\n");
- }
- if ( GenCC && GenAST )
- gen("ASTBase **_astp, *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");
- if ( GenCC ) genTokenPointers(q);
- if ( GenCC&&GenAST ) genASTPointers(q);
- if ( q->el_labels!=NULL ) genElementLabels(q->el_labels);
- if ( FoundException ) gen("int _signal=NoSignal;\n");
- if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
- if ( !GenCC ) gen("zzMake0;\n");
- if ( FoundException ) gen("*_retsignal = NoSignal;\n");
- if ( !GenCC ) gen("{\n");
-
- if ( has_guess_block_as_first_item((Junction *)q->p1) )
- {
- gen("zzGUESS_BLOCK\n");
- }
-
- /* L o o k F o r I n i t A c t i o n */
- if ( ((Junction *)q->p1)->jtype == aSubBlk )
- a = findImmedAction( ((Junction *)q->p1)->p1 );
- else
- a = findImmedAction( q->p1 ); /* only one alternative in rule */
- if ( a!=NULL && !a->is_predicate )
- {
- dumpAction(a->action, output, tabs, a->file, a->line, 1);
- a->done = 1; /* ignore action. We have already handled it */
- }
- if ( TraceGen )
- if ( GenCC ) {gen1("tracein(\"%s\");\n", q->rname);}
- else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);
-
- BlkLevel++;
- q->visited = TRUE; /* mark RULE as visited for FIRST/FOLLOW */
- f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly);
- if ( q->p1 != NULL )
- if ( ((Junction *)q->p1)->p2 != NULL )
- {tab(); makeErrorClause((Junction *)q->p1,f,max_k);}
- { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
- freeBlkFsets((Junction *)q->p1);
- q->visited = FALSE;
- --BlkLevel;
- if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
-
- if ( TraceGen )
- if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
- else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
-
- if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");
- /* E r r o r R e c o v e r y */
- NewSet();
- rk = empty;
- REACH(q->end, 1, &rk, follow);
- FillSet( follow );
- set_free( follow );
-
- _gen("fail:\n");
- if ( !GenCC ) gen("zzEXIT(zztasp1);\n");
- if ( FoundGuessBlk )
- if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}
- else gen("if ( guessing ) zzGUESS_FAIL;\n");
- if ( q->erraction!=NULL )
- dumpAction(q->erraction, output, tabs, q->file, q->line, 1);
- if ( GenCC )
- {
- gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
- r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
- }
- else
- {
- gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
- r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
- }
- gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);
-
- if ( TraceGen )
- if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
- else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
-
- if ( q->ret!=NULL ) {gen("return _retv;\n");}
- else if ( q->exceptions!=NULL ) gen("return;\n");
- if ( !GenCC ) gen("}\n");
-
- /* Gen code for exception handlers */
- if ( q->exceptions!=NULL )
- {
- gen("/* exception handlers */\n");
- dumpExceptions(q->exceptions);
- if ( !r->has_rule_exception )
- {
- _gen("_handler:\n");
- gen("zzdflthandlers(_signal,_retsignal);\n");
- }
- _gen("_adios:\n");
- if ( q->ret!=NULL ) {gen("return _retv;\n");}
- else {gen("return;\n");}
- }
- else if ( FoundException )
- {
- _gen("_handler:\n");
- gen("zzdflthandlers(_signal,_retsignal);\n");
- }
-
- tabs--;
- gen("}\n");
-
- if ( q->p2 != NULL ) {TRANS(q->p2);} /* generate code for next rule too */
- else dumpAfterActions( output );
- }
-
- static void
- #ifdef __USE_PROTOS
- DumpFuncHeader( Junction *q, RuleEntry *r )
- #else
- DumpFuncHeader( q, r )
- Junction *q;
- RuleEntry *r;
- #endif
- {
- /* A N S I */
- _gen("\n");
- if ( q->ret!=NULL )
- {
- if ( HasComma(q->ret) )
- {
- if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)
- else gen1("struct _rv%d\n",r->rulenum);
- }
- else
- {
- DumpType(q->ret, output);
- gen("\n");
- }
- }
- else
- {
- _gen("void\n");
- }
- if ( !GenCC ) _gen("#ifdef __STDC__\n");
- if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)
- else gen2("%s::%s(", CurrentClassName, q->rname);
- DumpANSIFunctionArgDef(output,q);
- _gen("\n");
-
- if ( GenCC ) {gen("{\n"); return;}
-
- /* K & R */
- gen("#else\n");
- gen2("%s%s(", RulePrefix, q->rname);
- if ( GenAST )
- {
- _gen("_root");
- if ( q->pdecl!=NULL ) _gen(",");
- }
- if ( FoundException )
- {
- if ( GenAST ) _gen(",");
- _gen("_retsignal");
- if ( q->pdecl!=NULL ) _gen(",");
- }
-
- DumpListOfParmNames( q->pdecl, output );
- gen(")\n");
- if ( GenAST ) gen("AST **_root;\n");
- if ( FoundException ) gen("int *_retsignal;\n");
- DumpOldStyleParms( q->pdecl, output );
- gen("#endif\n");
- gen("{\n");
- }
-
- void
- #ifdef __USE_PROTOS
- DumpANSIFunctionArgDef(FILE *f, Junction *q)
- #else
- DumpANSIFunctionArgDef(f,q)
- FILE *f;
- Junction *q;
- #endif
- {
- if ( GenAST )
- {
- if ( GenCC ) {fprintf(f,"ASTBase **_root");}
- else fprintf(f,"AST**_root");
- if ( q->pdecl!=NULL ) fprintf(f,",");
- }
- if ( FoundException )
- {
- if ( GenAST ) fprintf(f,",");
- fprintf(f,"int *_retsignal");
- if ( q->pdecl!=NULL ) fprintf(f,",");
- }
- if ( q->pdecl!=NULL ) {fprintf(f,"%s", q->pdecl);}
- else if ( !GenAST && !FoundException ) fprintf(f,"void");
- fprintf(f,")");
- }
-
- void
- #ifdef __USE_PROTOS
- genJunction( Junction *q )
- #else
- genJunction( q )
- Junction *q;
- #endif
- {
- require(q->ntype == nJunction, "genJunction: not junction");
- require(q->jtype == Generic, "genJunction: not generic junction");
-
- if ( q->p1 != NULL ) TRANS(q->p1);
- if ( q->p2 != NULL ) TRANS(q->p2);
- }
-
- void
- #ifdef __USE_PROTOS
- genEndBlk( Junction *q )
- #else
- genEndBlk( q )
- Junction *q;
- #endif
- {
- }
-
- void
- #ifdef __USE_PROTOS
- genEndRule( Junction *q )
- #else
- genEndRule( q )
- Junction *q;
- #endif
- {
- }
-
- void
- #ifdef __USE_PROTOS
- genHdr( int file )
- #else
- genHdr( file )
- int file;
- #endif
- {
- _gen("/*\n");
- _gen(" * A n t l r T r a n s l a t i o n H e a d e r\n");
- _gen(" *\n");
- _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
- _gen(" * Purdue University Electrical Engineering\n");
- _gen(" * With AHPCRC, University of Minnesota\n");
- _gen1(" * ANTLR Version %s\n", Version);
- _gen(" */\n");
- _gen("#include <stdio.h>\n");
- _gen1("#define ANTLR_VERSION %s\n", VersionDef);
- if ( strcmp(ParserName, DefaultParserName)!=0 )
- _gen2("#define %s %s\n", DefaultParserName, ParserName);
- if ( strcmp(ParserName, DefaultParserName)!=0 )
- {_gen1("#include \"%s\"\n", RemapFileName);}
- if ( GenLineInfo ) _gen2(LineInfoFormatStr, 1, FileStr[file]);
- if ( GenCC ) {
- if ( UserTokenDefsFile != NULL )
- fprintf(output, "#include %s\n", UserTokenDefsFile);
- else
- fprintf(output, "#include \"%s\"\n", DefFileName);
- }
-
- if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
- if ( !GenCC && FoundGuessBlk )
- {
- _gen("#define ZZCAN_GUESS\n");
- _gen("#include <setjmp.h>\n");
- }
- if ( FoundException )
- {
- _gen("#define EXCEPTION_HANDLING\n");
- _gen1("#define NUM_SIGNALS %d\n", NumSignals);
- }
- if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
- if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
- if ( GenAST ) {
- if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}
- else _gen("#include \"ast.h\"\n\n");
- }
- if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
- #ifdef DUM
- if ( !GenCC && LexGen ) {
- _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
- }
- #endif
- /* ###WARNING: This will have to change when SetWordSize changes */
- if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
- if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}
- else {
- _gen1("#include \"%s\"\n", APARSER_H);
- _gen1("#include \"%s.h\"\n", CurrentClassName);
- }
- if ( !GenCC ) {
- if ( UserDefdTokens )
- {_gen1("#include %s\n", UserTokenDefsFile);}
- /* still need this one as it has the func prototypes */
- _gen1("#include \"%s\"\n", DefFileName);
- }
- /* still need this one as it defines the DLG interface */
- if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");
- if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);
- if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);
- }
-
- void
- #ifdef __USE_PROTOS
- genHdr1( int file )
- #else
- genHdr1( file )
- int file;
- #endif
- {
- ListNode *p;
-
- genHdr(file);
- if ( GenAST )
- {
- if ( !GenCC ) {
- _gen("#include \"ast.c\"\n");
- _gen("zzASTgvars\n\n");
- }
- }
- if ( !GenCC ) _gen("ANTLR_INFO\n");
- if ( BeforeActions != NULL )
- {
- for (p = BeforeActions->next; p!=NULL; p=p->next)
- {
- UserAction *ua = (UserAction *)p->elem;
- dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
- }
- }
-
- if ( !FoundException ) return;
-
- if ( GenCC )
- {
- _gen1("\nvoid %s::\n", CurrentClassName);
- _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
- _gen("{\n");
- }
- else
- {
- _gen("\nvoid\n");
- _gen("#ifdef __STDC__\n");
- _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
- _gen("#else\n");
- _gen("zzdflthandlers( _signal, _retsignal )\n");
- _gen("int _signal;\n");
- _gen("int *_retsignal;\n");
- _gen("#endif\n");
- _gen("{\n");
- }
- tabs++;
- gen("*_retsignal = _signal;\n");
- if ( DefaultExGroup!=NULL )
- {
- dumpException(DefaultExGroup, 1);
- if ( !hasDefaultException(DefaultExGroup) )
- {
- gen("default :\n");
- tabs++;
- gen("*_retsignal = _signal;\n");
- tabs--;
- gen("}\n");
- }
- }
-
- tabs--;
- _gen("}\n\n");
- }
-
- void
- #ifdef __USE_PROTOS
- genStdPCCTSIncludeFile( FILE *f )
- #else
- genStdPCCTSIncludeFile( f )
- FILE *f;
- #endif
- {
- fprintf(f,"#ifndef STDPCCTS_H\n");
- fprintf(f,"#define STDPCCTS_H\n");
- fprintf(f,"/*\n");
- fprintf(f," * %s -- P C C T S I n c l u d e\n", stdpccts);
- fprintf(f," *\n");
- fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
- fprintf(f," * Purdue University Electrical Engineering\n");
- fprintf(f," * With AHPCRC, University of Minnesota\n");
- fprintf(f," * ANTLR Version %s\n", Version);
- fprintf(f," */\n");
- fprintf(f,"#include <stdio.h>\n");
- fprintf(f,"#define ANTLR_VERSION %s\n", VersionDef);
- if ( GenCC )
- {
- if ( UserDefdTokens )
- fprintf(f, "#include %s\n", UserTokenDefsFile);
- else {
- fprintf(f, "#include \"%s\"\n", DefFileName);
- }
-
- fprintf(f, "#include \"%s\"\n", ATOKEN_H);
-
- if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
-
- fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);
-
- if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
- if ( GenAST ) {
- fprintf(f, "#include \"%s\"\n", ASTBASE_H);
- }
- fprintf(f,"#include \"%s\"\n", APARSER_H);
- fprintf(f,"#include \"%s.h\"\n", CurrentClassName);
- if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);
- fprintf(f, "#endif\n");
- return;
- }
-
- if ( strcmp(ParserName, DefaultParserName)!=0 )
- fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);
- if ( strcmp(ParserName, DefaultParserName)!=0 )
- fprintf(f, "#include \"%s\"\n", RemapFileName);
- if ( UserTokenDefsFile != NULL )
- fprintf(f, "#include %s\n", UserTokenDefsFile);
- if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
- if ( FoundGuessBlk )
- {
- fprintf(f,"#define ZZCAN_GUESS\n");
- fprintf(f,"#include <setjmp.h>\n");
- }
- if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);
- if ( GenAST ) fprintf(f,"#define GENAST\n");
- if ( FoundException )
- {
- _gen("#define EXCEPTION_HANDLING\n");
- _gen1("#define NUM_SIGNALS %d\n", NumSignals);
- }
- if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
- #ifdef DUM
- if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
- #endif
- /* ###WARNING: This will have to change when SetWordSize changes */
- fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
- fprintf(f,"#include \"antlr.h\"\n");
- if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");
- if ( UserDefdTokens )
- fprintf(f, "#include %s\n", UserTokenDefsFile);
- /* still need this one as it has the func prototypes */
- fprintf(f, "#include \"%s\"\n", DefFileName);
- /* still need this one as it defines the DLG interface */
- fprintf(f,"#include \"dlgdef.h\"\n");
- /* don't need this one unless DLG is used */
- if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);
- fprintf(f,"#endif\n");
- }
-
- /* dump action 's' to file 'output' starting at "local" tab 'tabs'
- Dump line information in front of action if GenLineInfo is set
- If file == -1 then GenLineInfo is ignored.
- The user may redefine the LineInfoFormatStr to his/her liking
- most compilers will like the default, however.
-
- June '93; changed so that empty lines are left alone so that
- line information is correct for the compiler/debuggers.
- */
- void
- #ifdef __USE_PROTOS
- dumpAction( char *s, FILE *output, int tabs, int file, int line,
- int final_newline )
- #else
- dumpAction( s, output, tabs, file, line, final_newline )
- char *s;
- FILE *output;
- int tabs;
- int file;
- int line;
- int final_newline;
- #endif
- {
- int inDQuote, inSQuote;
- require(s!=NULL, "dumpAction: NULL action");
- require(output!=NULL, eMsg1("dumpAction: output FILE is NULL for %s",s));
-
- if ( GenLineInfo && file != -1 )
- {
- fprintf(output, LineInfoFormatStr, line, FileStr[file]);
- }
- PastWhiteSpace( s );
- /* don't print a tab if first non-white char is a # (preprocessor command) */
- if ( *s!='#' ) {TAB;}
- inDQuote = inSQuote = FALSE;
- while ( *s != '\0' )
- {
- if ( *s == '\\' )
- {
- fputc( *s++, output ); /* Avoid '"' Case */
- if ( *s == '\0' ) return;
- if ( *s == '\'' ) fputc( *s++, output );
- if ( *s == '\"' ) fputc( *s++, output );
- }
- if ( *s == '\'' )
- {
- if ( !inDQuote ) inSQuote = !inSQuote;
- }
- if ( *s == '"' )
- {
- if ( !inSQuote ) inDQuote = !inDQuote;
- }
- if ( *s == '\n' )
- {
- fputc('\n', output);
- s++;
- PastWhiteSpace( s );
- if ( *s == '}' )
- {
- --tabs;
- TAB;
- fputc( *s++, output );
- continue;
- }
- if ( *s == '\0' ) return;
- if ( *s != '#' ) /* #define, #endif etc.. start at col 1 */
- {
- TAB;
- }
- }
- if ( *s == '}' && !(inSQuote || inDQuote) )
- {
- --tabs; /* Indent one fewer */
- }
- if ( *s == '{' && !(inSQuote || inDQuote) )
- {
- tabs++; /* Indent one more */
- }
- fputc( *s, output );
- s++;
- }
- if ( final_newline ) fputc('\n', output);
- }
-
- static void
- #ifdef __USE_PROTOS
- dumpAfterActions( FILE *output )
- #else
- dumpAfterActions( output )
- FILE *output;
- #endif
- {
- ListNode *p;
- require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
- if ( AfterActions != NULL )
- {
- for (p = AfterActions->next; p!=NULL; p=p->next)
- {
- UserAction *ua = (UserAction *)p->elem;
- dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
- }
- }
- fclose( output );
- }
-
- /*
- * Find the next action in the stream of execution. Do not pass
- * junctions with more than one path leaving them.
- * Only pass generic junctions.
- *
- * Scan forward while (generic junction with p2==NULL)
- * If we stop on an action, return ptr to the action
- * else return NULL;
- */
- static ActionNode *
- #ifdef __USE_PROTOS
- findImmedAction( Node *q )
- #else
- findImmedAction( q )
- Node *q;
- #endif
- {
- Junction *j;
- require(q!=NULL, "findImmedAction: NULL node");
- require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
-
- while ( q->ntype == nJunction )
- {
- j = (Junction *)q;
- if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
- q = j->p1;
- if ( q == NULL ) return NULL;
- }
- if ( q->ntype == nAction ) return (ActionNode *)q;
- return NULL;
- }
-
- static void
- #ifdef __USE_PROTOS
- dumpRetValAssign( char *retval, char *ret_def )
- #else
- dumpRetValAssign( retval, ret_def )
- char *retval;
- char *ret_def;
- #endif
- {
- char *q = ret_def;
-
- tab();
- while ( *retval != '\0' )
- {
- while ( isspace((*retval)) ) retval++;
- while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);
- fprintf(output, " = _trv.");
-
- DumpNextNameInDef(&q, output);
- fputc(';', output); fputc(' ', output);
- if ( *retval == ',' ) retval++;
- }
- }
-
- /* This function computes the set of tokens that can possibly be seen k
- * tokens in the future from point j
- */
- static set
- #ifdef __USE_PROTOS
- ComputeErrorSet( Junction *j, int k )
- #else
- ComputeErrorSet( j, k )
- Junction *j;
- int k;
- #endif
- {
- Junction *alt1;
- set a, rk, f;
- require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");
-
- f = rk = empty;
- for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
- {
- REACH(alt1->p1, k, &rk, a);
- require(set_nil(rk), "ComputeErrorSet: rk != nil");
- set_free(rk);
- set_orin(&f, a);
- set_free(a);
- }
- return f;
- }
-
- static char *
- #ifdef __USE_PROTOS
- tokenFollowSet(TokNode *p)
- #else
- tokenFollowSet(p)
- TokNode *p;
- #endif
- {
- static char buf[100];
- set rk, a;
- int n;
- rk = empty;
-
- REACH(p->next, 1, &rk, a);
- require(set_nil(rk), "rk != nil");
- set_free(rk);
- n = DefErrSet( &a, 0, NULL );
- set_free(a);
- if ( GenCC )
- sprintf(buf, "err%d", n);
- else
- sprintf(buf, "zzerr%d", n);
- return buf;
- }
-
- static void
- #ifdef __USE_PROTOS
- makeErrorClause( Junction *q, set f, int max_k )
- #else
- makeErrorClause( q, f, max_k )
- Junction *q;
- set f;
- int max_k;
- #endif
- {
- if ( FoundException )
- {
- _gen("else {\n");
- tabs++;
- if ( FoundGuessBlk )
- {
- if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
- else gen("if ( zzguessing ) goto fail;\n");
- }
- gen("if (_sva) _signal=NoViableAlt;\n");
- gen("else _signal=NoSemViableAlt;\n");
- gen("goto _handler;\n");
- tabs--;
- gen("}\n");
- return;
- }
-
- if ( max_k == 1 )
- {
- if ( GenCC ) {_gen1("else {FAIL(1,err%d", DefErrSet(&f,1,NULL));}
- else _gen1("else {zzFAIL(1,zzerr%d", DefErrSet(&f,1,NULL))
- set_free(f);
- }
- else
- {
- int i;
- set_free(f);
- if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}
- else _gen1("else {zzFAIL(%d", max_k);
- for (i=1; i<=max_k; i++)
- {
- f = ComputeErrorSet(q, i);
- if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}
- else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));
-
- set_free(f);
- }
- }
- _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
- }
-